package com.jgp.security.shiro.component;

import com.jgp.common.utils.JGPUtil;
import com.jgp.security.config.SecUserAdapter;
import com.jgp.security.pojo.UserInfo;
import com.jgp.security.props.SecurityConfigPropBean;
import com.jgp.security.secmodel.SecUser;
import com.jgp.security.service.SecUserService;
import com.jgp.security.shiro.cache.RedisSessionDAO;
import com.jgp.sys.utils.SpringContextUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.util.ThreadContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

/**
 * 项目   jgp-cloud-parent
 * 作者   loufei
 * 时间   2019/1/10
 */
@Component
public class ShiroUserAdapter implements SecUserAdapter {
    
    @Autowired
    private SecurityConfigPropBean securityConfigPropBean;
    @Autowired
    private RedisSessionDAO sessionDAO;
    
    private AesCipherService aesCipherService = new AesCipherService();
    
    public static void main(String[] args) {
        System.out.println(new ShiroUserAdapter().encryptPwd("yantai0535", "@adc==", 2));
    }
    
    @Override
    public boolean checkPwd(String userId, String pwd) throws IOException {
        SecUserService userService = SpringContextUtil.getBean(SecUserService.class);
        SecUser user = userService.query(userId);
        if (securityConfigPropBean.getDbPassType().equalsIgnoreCase("md5")) {
            return user.getPassword().equals(encryptPwd(pwd, user.getSugar(), user.getEncryptTime()));
        } else if (securityConfigPropBean.getDbPassType().equalsIgnoreCase("aes")) {
            return pwd.equals(decryptDbPwdAes(user.getPassword()));
        } else {
            return false;
        }
    }
    
    @Override
    public void resetPwd(String userId, String pwd) {
        SecUserService userService = SpringContextUtil.getBean(SecUserService.class);
        userService.resetPassword(userId, pwd);
    }
    
    @Override
    public String encryptPwd(String plainPwd, String sugar, Integer encryptTime) {
        Md5Hash hash = new Md5Hash(plainPwd, sugar, encryptTime);
        return hash.toHex();
    }
    
    @Override
    public String decryptDbPwdAes(String dbPwd) throws IOException {
        aesCipherService.setKeySize(128);
        Path keyFilePath = Paths.get(securityConfigPropBean.getAesKeyFile());
        if (Files.exists(keyFilePath)) {
            byte[] key = Files.readAllBytes(keyFilePath);
            String dbPass = new String(aesCipherService.decrypt(Hex.decode(dbPwd), key).getBytes());
            return dbPass;
        } else {
            throw new IOException("没有找到秘钥文件！！");
        }
    }
    
    @Override
    public SecUser operatorPwd(SecUser user, String pwd) throws IOException {
        
        if (securityConfigPropBean.getDbPassType().equalsIgnoreCase("md5")) {
            String sugar = JGPUtil.randomStr(JGPUtil.random(3, 5));
            int encryptTime = JGPUtil.random(3, 5);
            user.setSugar(sugar);
            user.setEncryptTime(encryptTime);
            user.setPassword(encryptPwd(pwd, sugar, encryptTime));
        } else {
            Path keyFilePath = Paths.get(securityConfigPropBean.getAesKeyFile());
            if (Files.exists(keyFilePath)) {
                aesCipherService.setKeySize(128);
                byte[] key = Files.readAllBytes(keyFilePath);
                String encrptText = aesCipherService.encrypt(pwd.getBytes(), key).toHex();
                user.setPassword(encrptText);
            } else {
                throw new IOException("没有找到秘钥文件！！");
            }
        }
        
        
        return user;
    }
    
    @Override
    public UserInfo currentUser() {
        if (Objects.isNull(ThreadContext.getSecurityManager())) {
            return null;
        }
        UserInfo user = (UserInfo) SecurityUtils.getSubject().getPrincipal();
        return user;
    }
    
    @Override
    public UserInfo getUserInfoBySessionId(String sessionId) {
        Session session = sessionDAO.doReadSession(sessionId);
        Object principalAttr = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
        SimplePrincipalCollection principal = (SimplePrincipalCollection) principalAttr;
        return (UserInfo) principal.getPrimaryPrincipal();
    }
}
